package galaxies;

import galaxies.enums.EGalaxyType;
import gameAppLayer.GameSettings;

import java.awt.Polygon;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import utilities.CoordConvert;
import utilities.HexLocationLoader;
import utilities.PointRotate;

//import com.bea.xml.stream.XMLOutputFactoryBase;

public class GalaxySizeCalculator {

	public Random rand = new Random();
	public HashMap<String, Double> rotations = new HashMap<String, Double>();
	
	public int numStars;
	
	public HashMap<String, ArrayList<ArrayList<Integer>>> calcGalaxyDims(GameSettings settings) {
		
		ArrayList<String> refs = settings.getGalaxyRefs();
		HashMap<String, ArrayList<ArrayList<Integer>>> sizes = new HashMap<String, ArrayList<ArrayList<Integer>>>();
		//int numGalaxies = settings.getGalaxyRefs().size();
		
		int density;
		EGalaxyType type;
		int size;		
		
		for (String ref: refs) { //int i = 0; i < numGalaxies; i++) {
			density = settings.getGalaxyDensity(ref);
			type = settings.getGalaxyType(ref);
			size = settings.getGalSizes(ref);
			
			ArrayList<ArrayList<Integer>> dims = new ArrayList<ArrayList<Integer>>();
			
			//Generate rotation
			double rotation = rand.nextDouble()*Math.PI*2;
			rotations.put(ref, rotation);
						
			if (type.equals(EGalaxyType.BAR_SPIRAL)) {
				dims.addAll(calcSpiralDims(size));
			}
			else if (type.equals(EGalaxyType.CUSTOM)) {
				dims.addAll(calcCustomDims(size));
				//sizes.put(ref, calcCustomDims(size, density, settings.getFileLocation()));
			}
			else if (type.equals(EGalaxyType.ELLIPTICAL)) {
				dims.addAll(calcEllipseDims(size));
			}
			else if (type.equals(EGalaxyType.SPIRAL)) {
				dims.addAll(calcSpiralDims(size));
			}
			else if (type.equals(EGalaxyType.UNIFORM)) {
				dims.addAll(calcUniformDims(size));
			}
			else {
				dims = null;
			}
			
			for (ArrayList<Integer> point: dims) {
				PointRotate.simpleRotate(rotation, point);
			}			
			
			sizes.put(ref, dims);
		}
		
		return sizes;
	}
	
	
	public ArrayList<ArrayList<Integer>> calcUniformDims(int galSize) {
		
//		int minTiles = galSize.getMinTiles();
//		int maxTiles = galSize.getMaxTiles();		
//		//this.numStars = (int) (minStars + rand.nextDouble()*(maxStars - minStars));
//		
//		//int tilesPerStar = density.getUniformTiles();
//		int totalTiles = (int) (minTiles + rand.nextDouble()*(maxTiles - minTiles));//numStars + numStars*tilesPerStar;
		
		return null;
	}
	//Bar spiral dims are calculated the exact same way as spiral dims
	public ArrayList<ArrayList<Integer>> calcSpiralDims(int galSize) {		
		ArrayList<ArrayList<Integer>> dims = new ArrayList<ArrayList<Integer>>();
		
		//circle, area = pi*r^2
		int tempDim = (int) (Math.sqrt(galSize/Math.PI));
		int dim = (int) (tempDim + tempDim*(1-Math.cos(Math.PI/6)));
		
		double resolution = 200;
		double theta = 0;
		double thetaStep = 2*Math.PI/resolution;
		
		int x, y;
		ArrayList<Integer> points;
		for (theta = 0; theta < 2*Math.PI; theta+=thetaStep) {
			points = new ArrayList<Integer>();
			x = (int) (dim*Math.cos(theta));
			y = (int) (dim*Math.sin(theta));
			points.add(x);
			points.add(y);
			
			dims.add(points);
		}
		
		return dims;
	}
	
	public ArrayList<ArrayList<Integer>> calcEllipseDims(int galSize) {
		ArrayList<ArrayList<Integer>> dims = new ArrayList<ArrayList<Integer>>();
		
		double longAxis = 1.0;
		double shortAxis = 0.5+rand.nextDouble()*0.5;
		//double shortFraction = shortAxis/longAxis;
		
		//ellipse, area = pi*a*b, where a, b are longDim, shortDim respectively 
		int longDim = (int) Math.sqrt(galSize/(Math.PI*shortAxis*shortAxis));
		int shortDim = (int) Math.sqrt(galSize/(Math.PI*longAxis*longAxis));

		double resolution = 200;
		double theta = 0;
		double thetaStep = 2*Math.PI/resolution;
		
		int x, y;
		ArrayList<Integer> points;
		for (theta = 0; theta < 2*Math.PI; theta+=thetaStep) {
			points = new ArrayList<Integer>();
			x = (int) (longDim*Math.cos(theta));
			y = (int) (shortDim*Math.sin(theta));
			points.add(x);
			points.add(y);
			
			dims.add(points);
		}
		return dims;
	}
	
	/*
	 * Places any custom map onto a circular background grid
	 */
	public ArrayList<ArrayList<Integer>> calcCustomDims(int galSize) {
		
		ArrayList<ArrayList<Integer>> dims = new ArrayList<ArrayList<Integer>>();
		
		//circle, area = pi*r^2
		int tempDim = (int) (Math.sqrt(galSize/Math.PI));
		int dim = (int) (tempDim + tempDim*(1-Math.cos(Math.PI/6)));
				
		double resolution = 200;
		double theta = 0;
		double thetaStep = 2*Math.PI/resolution;
				
		int x, y;
		ArrayList<Integer> points;
		for (theta = 0; theta < 2*Math.PI; theta+=thetaStep) {
			points = new ArrayList<Integer>();
			x = (int) (dim*Math.cos(theta));
			y = (int) (dim*Math.sin(theta));
			points.add(x);
			points.add(y);
			
			dims.add(points);
		}
		
		return dims;
	}
}
